---
title: "Simple Storage"
description: "Persistent key-value storage for MentraOS Apps with local caching and cloud sync"
---

## Overview

The Simple Storage module provides a localStorage-like interface for MentraOS Apps to persistently store configuration data, user preferences, and small datasets. Data is automatically synchronized between your app server and the MentraOS Cloud, with intelligent local caching for optimal performance.

<Note>
Simple Storage data is isolated by userId and packageName, ensuring each user has private storage that other apps cannot access.
</Note>

## Getting Started

Access Simple Storage through your AppSession:

```typescript
import { AppServer, AppSession } from '@mentraos/sdk';

class MyAppServer extends AppServer {
  protected async onSession(session: AppSession, sessionId: string, userId: string) {
    // Simple Storage is available on every session
    const storage = session.simpleStorage;
    
    // Store user preference
    await storage.set('theme', 'dark');
    
    // Retrieve it later
    const theme = await storage.get('theme'); // 'dark'
  }
}
```

## Basic Operations

### Set Item

Store a key-value pair:

```typescript
// Store different data types
await session.simpleStorage.set('username', 'john_doe');
await session.simpleStorage.set('lastLogin', Date.now().toString());
await session.simpleStorage.set('preferences', JSON.stringify({
  theme: 'dark',
  notifications: true
}));
```

### Get Item

Retrieve a stored value:

```typescript
const username = await session.simpleStorage.get('username');
if (username) {
  console.log(`Welcome back, ${username}!`);
} else {
  console.log('First time user');
}

// Handle complex data
const prefsJson = await session.simpleStorage.get('preferences');
if (prefsJson) {
  const preferences = JSON.parse(prefsJson);
  console.log('User theme:', preferences.theme);
}
```

### Check if Key Exists

```typescript
const hasUsername = await session.simpleStorage.hasKey('username');
if (!hasUsername) {
  // Show username setup flow
}
```

### Delete Item

```typescript
await session.simpleStorage.delete('temporaryData');
```

### Clear All Data

```typescript
// Clear all storage for this user
await session.simpleStorage.clear();
```

## Advanced Operations

### Get All Keys

```typescript
const allKeys = await session.simpleStorage.keys();
console.log('Stored keys:', allKeys); // ['username', 'theme', 'lastLogin']
```

### Get Storage Size

```typescript
const size = await session.simpleStorage.size();
console.log(`${size} items stored`);
```

### Get All Data

```typescript
const allData = await session.simpleStorage.getAllData();
console.log('Complete storage:', allData);
// { username: 'john_doe', theme: 'dark', lastLogin: '1234567890' }
```

### Set Multiple Items

```typescript
await session.simpleStorage.setMultiple({
  'setting1': 'value1',
  'setting2': 'value2',
  'setting3': 'value3'
});
```

## Data Types and Serialization

Simple Storage stores all data as strings. For complex data, use JSON:

```typescript
// Storing objects
const userData = {
  name: 'John',
  age: 30,
  preferences: { theme: 'dark' }
};
await storage.set('user', JSON.stringify(userData));

// Retrieving objects
const userJson = await storage.get('user');
const user = userJson ? JSON.parse(userJson) : null;

// Storing arrays
const tags = ['work', 'important', 'project'];
await storage.set('tags', JSON.stringify(tags));

// Storing numbers/booleans
await storage.set('count', '42');
await storage.set('enabled', 'true');
```

## Performance and Caching

Simple Storage implements intelligent caching for optimal performance:

```typescript
// First call fetches from cloud and caches locally
const theme = await storage.get('theme'); // Network request

// Subsequent calls use cache (fast)
const theme2 = await storage.get('theme'); // No network request

// Set operations update cache immediately (optimistic updates)
await storage.set('theme', 'light'); // Cache updated instantly
```

<Warning>
The cache is per-session. If you need fresh data from the cloud, create a new session or restart your app.
</Warning>

## Common Patterns

### User Preferences

```typescript
class PreferencesManager {
  constructor(private storage: SimpleStorage) {}
  
  async getTheme(): Promise<'light' | 'dark'> {
    return (await this.storage.get('theme') as 'light' | 'dark') || 'light';
  }
  
  async setTheme(theme: 'light' | 'dark'): Promise<void> {
    await this.storage.set('theme', theme);
  }
  
  async getNotificationSettings() {
    const json = await this.storage.get('notifications');
    return json ? JSON.parse(json) : { enabled: true, sound: true };
  }
}
```

### Session State

```typescript
// Save app state when user pauses
await session.simpleStorage.setMultiple({
  'currentPage': 'dashboard',
  'scrollPosition': '150',
  'selectedItems': JSON.stringify(['item1', 'item2'])
});

// Restore state when user returns
const currentPage = await session.simpleStorage.get('currentPage') || 'home';
const scrollPos = parseInt(await session.simpleStorage.get('scrollPosition') || '0');
```

### Feature Flags

```typescript
// Check if user has seen onboarding
const hasSeenOnboarding = await session.simpleStorage.hasKey('onboardingComplete');
if (!hasSeenOnboarding) {
  // Show onboarding flow
  await showOnboarding();
  await session.simpleStorage.set('onboardingComplete', 'true');
}
```

### Analytics and Tracking

```typescript
// Track usage statistics
const loginCountStr = await session.simpleStorage.get('loginCount') || '0';
const loginCount = parseInt(loginCountStr) + 1;
await session.simpleStorage.set('loginCount', loginCount.toString());

// Track feature usage
const featuresUsed = await session.simpleStorage.get('featuresUsed');
const features = featuresUsed ? JSON.parse(featuresUsed) : [];
if (!features.includes('voice_commands')) {
  features.push('voice_commands');
  await session.simpleStorage.set('featuresUsed', JSON.stringify(features));
}
```











## Error Handling

Simple Storage methods handle errors gracefully:

```typescript
try {
  await session.simpleStorage.set('key', 'value');
} catch (error) {
  console.error('Failed to store data:', error);
  // Storage operation failed - handle appropriately
}

// Get operations return undefined on error
const value = await session.simpleStorage.get('key');
if (value === undefined) {
  // Either key doesn't exist or error occurred
  console.log('No value found or error occurred');
}
```

## Best Practices

<AccordionGroup>
  <Accordion title="Data Size Limits">
    - Keep individual values under 1MB
    - Total storage per user should be reasonable (< 10MB)
    - For large data, use external storage solutions
  </Accordion>

  <Accordion title="Key Naming">
    ```typescript
    // Good key names
    'user.theme'
    'app.lastSyncTime'
    'feature.onboardingComplete'
    
    // Avoid
    'temp_data_123'
    'x'
    'really_long_key_name_that_describes_everything'
    ```
  </Accordion>

  <Accordion title="JSON Serialization">
    ```typescript
    // Always handle JSON errors
    const parseStoredJson = async (key: string) => {
      try {
        const json = await storage.get(key);
        return json ? JSON.parse(json) : null;
      } catch (error) {
        console.error(`Invalid JSON in storage key ${key}:`, error);
        return null;
      }
    };
    ```
  </Accordion>

  <Accordion title="Default Values">
    ```typescript
    // Provide sensible defaults
    const getTheme = async (): Promise<'light' | 'dark'> => {
      const stored = await storage.get('theme');
      return (stored as 'light' | 'dark') || 'light';
    };
    ```
  </Accordion>
</AccordionGroup>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Data Not Persisting">
    - Ensure your app has proper authentication (package name and API key)
    - Check that userId is consistent across sessions
    - Verify network connectivity between your server and MentraOS Cloud
  </Accordion>

  <Accordion title="Cache Issues">
    - Cache is per-session - restart session to get fresh data
    - Storage operations update cache optimistically
    - Network errors may cause cache/cloud desynchronization
  </Accordion>

  <Accordion title="Performance Issues">
    - Use `hasKey()` instead of `get()` for existence checks
    - Batch multiple operations when possible with `setMultiple()`
    - Consider caching frequently accessed data in memory
  </Accordion>
</AccordionGroup>

## API Reference

| Method | Return Type | Description |
|--------|-------------|-------------|
| `get(key)` | `Promise<string \| undefined>` | Get value by key |
| `set(key, value)` | `Promise<void>` | Set key-value pair |
| `hasKey(key)` | `Promise<boolean>` | Check if key exists |
| `delete(key)` | `Promise<boolean>` | Delete key |
| `clear()` | `Promise<boolean>` | Clear all data |
| `keys()` | `Promise<string[]>` | Get all keys |
| `size()` | `Promise<number>` | Get number of items |
| `getAllData()` | `Promise<Record<string, string>>` | Get all data |
| `setMultiple(data)` | `Promise<void>` | Set multiple items |

<Info>
Simple Storage is perfect for configuration data, user preferences, and small datasets. For larger data or file storage, consider using dedicated cloud storage solutions or databases.
</Info>